<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
<!-- richtext.qdoc -->
  <title>Rich Text Document Structure | Qt GUI 5.14.2</title>
  <link rel="stylesheet" type="text/css" href="style/offline-simple.css" />
  <script type="text/javascript">
    document.getElementsByTagName("link").item(0).setAttribute("href", "style/offline.css");
    // loading style sheet breaks anchors that were jumped to before
    // so force jumping to anchor again
    setTimeout(function() {
        var anchor = location.hash;
        // need to jump to different anchor first (e.g. none)
        location.hash = "#";
        setTimeout(function() {
            location.hash = anchor;
        }, 0);
    }, 0);
  </script>
</head>
<body>
<div class="header" id="qtdocheader">
  <div class="main">
    <div class="main-rounded">
      <div class="navigationbar">
        <table><tr>
<td ><a href="../qtdoc/index.html">Qt 5.14</a></td><td ><a href="qtgui-index.html">Qt GUI</a></td><td >Rich Text Document Structure</td></tr></table><table class="buildversion"><tr>
<td id="buildversion" width="100%" align="right"><a href="qtgui-index.html">Qt 5.14.2 Reference Documentation</a></td>
        </tr></table>
      </div>
    </div>
<div class="content">
<div class="line">
<div class="content mainContent">
  <link rel="prev" href="richtext.html" />
  <link rel="next" href="richtext-cursor.html" />
<p class="naviNextPrevious headerNavi">
<a class="prevPage" href="richtext.html">Rich Text Processing</a>
<span class="naviSeparator">  &#9702;  </span>
<a class="nextPage" href="richtext-cursor.html">The QTextCursor Interface</a>
</p><p/>
<div class="sidebar">
<div class="toc">
<h3><a name="toc">Contents</a></h3>
<ul>
<li class="level1"><a href="#rich-text-documents">Rich Text Documents</a></li>
<li class="level1"><a href="#document-elements">Document Elements</a></li>
<li class="level2"><a href="#text-blocks">Text Blocks</a></li>
<li class="level2"><a href="#frames">Frames</a></li>
<li class="level2"><a href="#tables">Tables</a></li>
<li class="level2"><a href="#lists">Lists</a></li>
<li class="level2"><a href="#images">Images</a></li>
</ul>
</div>
<div class="sidebar-content" id="sidebar-content"></div></div>
<h1 class="title">Rich Text Document Structure</h1>
<span class="subtitle"></span>
<!-- $$$richtext-structure.html-description -->
<div class="descr"> <a name="details"></a>
<p>Text documents are represented by the <a href="qtextdocument.html">QTextDocument</a> class, which contains information about the document's internal representation, its structure, and keeps track of modifications to provide undo/redo facilities.</p>
<p>The structured representation of a text document presents its contents as a hierarchy of text blocks, frames, tables, and other objects. These provide a logical structure to the document and describe how their contents will be displayed. Generally, frames and tables are used to group other structures while text blocks contain the actual textual information.</p>
<p>New elements are created and inserted into the document programmatically <a href="richtext-cursor.html">with a QTextCursor</a> or by using an editor widget, such as <a href="../qtwidgets/qtextedit.html">QTextEdit</a>. Elements can be given a particular format when they are created; otherwise they take the cursor's current format for the element.</p>
<div class="table"><table class="generic">
 <tr valign="top" class="odd"><td ><img src="images/richtext-document.png" alt="" /></td><td ><b>Basic structure</b><p>The &quot;top level&quot; of a document might be populated in the way shown. Each document always contains a root frame, and this always contains at least one text block.</p>
<p>For documents with some textual content, the root frame usually contains a sequence of blocks and other elements.</p>
<p>Sequences of frames and tables are always separated by text blocks in a document, even if the text blocks contain no information. This ensures that new elements can always be inserted between existing structures.</p>
</td></tr>
</table></div>
<p>In this chapter, we look at each of the structural elements used in a rich text document, outline their features and uses, and show how to examine their contents. Document editing is described in <a href="richtext-cursor.html">The QTextCursor Interface</a>.</p>
<a name="rich-text-documents"></a>
<h2 id="rich-text-documents">Rich Text Documents</h2>
<p><a href="qtextdocument.html">QTextDocument</a> objects contain all the information required to construct rich text documents. Text documents can be accessed in two complementary ways: as a linear buffer for editors to use, and as an object hierarchy that is useful to layout engines. In the hierarchical document model, objects generally correspond to visual elements such as frames, tables, and lists. At a lower level, these elements describe properties such as the text style and alignment. The linear representation of the document is used for editing and manipulation of the document's contents.</p>
<p>Although <a href="../qtwidgets/qtextedit.html">QTextEdit</a> makes it easy to display and edit rich text, documents can also be used independently of any editor widget, for example:</p>
<pre class="cpp">

  <span class="type"><a href="qtextdocument.html">QTextDocument</a></span> <span class="operator">*</span>newDocument <span class="operator">=</span> <span class="keyword">new</span> <span class="type"><a href="qtextdocument.html">QTextDocument</a></span>;

</pre>
<p>Alternatively, they can be extracted from an existing editor:</p>
<pre class="cpp">

  <span class="type"><a href="../qtwidgets/qtextedit.html">QTextEdit</a></span> <span class="operator">*</span>editor <span class="operator">=</span> <span class="keyword">new</span> <span class="type"><a href="../qtwidgets/qtextedit.html">QTextEdit</a></span>;
  <span class="type"><a href="qtextdocument.html">QTextDocument</a></span> <span class="operator">*</span>editorDocument <span class="operator">=</span> editor<span class="operator">-</span><span class="operator">&gt;</span>document();

</pre>
<p>This flexibility enables applications to handle multiple rich text documents without the overhead of multiple editor widgets, or requiring documents to be stored in some intermediate format.</p>
<p>An empty document contains a root frame which itself contains a single empty text block. Frames provide logical separation between parts of the document, but also have properties that determine how they will appear when rendered. A table is a specialized type of frame that consists of a number of cells, arranged into rows and columns, each of which can contain further structure and text. Tables provide management and layout features that allow flexible configurations of cells to be created.</p>
<p>Text blocks contain text fragments, each of which specifies text and character format information. Textual properties are defined both at the character level and at the block level. At the character level, properties such as font family, text color, and font weight can be specified. The block level properties control the higher level appearance and behavior of the text, such as the direction of text flow, alignment, and background color.</p>
<p>The document structure is not manipulated directly. Editing is performed through a cursor-based interface. The <a href="richtext-cursor.html">text cursor interface</a> automatically inserts new document elements into the root frame, and ensures that it is padded with empty blocks where necessary.</p>
<p>We obtain the root frame in the following manner:</p>
<pre class="cpp">

      <span class="type"><a href="qtextdocument.html">QTextDocument</a></span> <span class="operator">*</span>textDocument;
      <span class="type"><a href="qtextframe.html">QTextFrame</a></span> <span class="operator">*</span>root <span class="operator">=</span> textDocument<span class="operator">-</span><span class="operator">&gt;</span>rootFrame();

</pre>
<p>When navigating the document structure, it is useful to begin at the root frame because it provides access to the entire document structure.</p>
<a name="document-elements"></a>
<h2 id="document-elements">Document Elements</h2>
<p>Rich text documents usually consist of common elements such as paragraphs, frames, tables, and lists. These are represented in a <a href="qtextdocument.html">QTextDocument</a> by the <a href="qtextblock.html">QTextBlock</a>, <a href="qtextframe.html">QTextFrame</a>, <a href="qtexttable.html">QTextTable</a>, and <a href="qtextlist.html">QTextList</a> classes. Unlike the other elements in a document, images are represented by specially formatted text fragments. This enables them to be placed formatted inline with the surrounding text.</p>
<p>The basic structural building blocks in documents are <a href="qtextblock.html">QTextBlock</a> and <a href="qtextframe.html">QTextFrame</a>. Blocks themselves contain fragments of rich text (<a href="qtextfragment.html">QTextFragment</a>), but these do not directly influence the high level structure of a document.</p>
<p>Elements which can group together other document elements are typically subclasses of <a href="qtextobject.html">QTextObject</a>, and fall into two categories: Elements that group together text blocks are subclasses of <a href="qtextblockgroup.html">QTextBlockGroup</a>, and those that group together frames and other elements are subclasses of <a href="qtextframe.html">QTextFrame</a>.</p>
<a name="text-blocks"></a>
<h3 id="text-blocks">Text Blocks</h3>
<p>Text blocks are provided by the <a href="qtextblock.html">QTextBlock</a> class.</p>
<p>Text blocks group together fragments of text with different character formats, and are used to represent paragraphs in the document. Each block typically contains a number of text fragments with different styles. Fragments are created when text is inserted into the document, and more of them are added when the document is edited. The document splits, merges, and removes fragments to efficiently represent the different styles of text in the block.</p>
<p>The fragments within a given block can be examined by using a <a href="qtextblock-iterator.html">QTextBlock::iterator</a> to traverse the block's internal structure:</p>
<pre class="cpp">

      <span class="type"><a href="qtextblock.html">QTextBlock</a></span><span class="operator">::</span>iterator it;
      <span class="keyword">for</span> (it <span class="operator">=</span> currentBlock<span class="operator">.</span>begin(); <span class="operator">!</span>(it<span class="operator">.</span>atEnd()); <span class="operator">+</span><span class="operator">+</span>it) {
          <span class="type"><a href="qtextfragment.html">QTextFragment</a></span> currentFragment <span class="operator">=</span> it<span class="operator">.</span>fragment();
          <span class="keyword">if</span> (currentFragment<span class="operator">.</span>isValid())
              processFragment(currentFragment);
      }

</pre>
<p>Blocks are also used to represent list items. As a result, blocks can define their own character formats which contain information about block-level decoration, such as the type of bullet points used for list items. The formatting for the block itself is described by the <a href="qtextblockformat.html">QTextBlockFormat</a> class, and describes properties such as text alignment, indentation, and background color.</p>
<p>Although a given document may contain complex structures, once we have a reference to a valid block in the document, we can navigate between each of the text blocks in the order in which they were written:</p>
<pre class="cpp">

      <span class="type"><a href="qtextblock.html">QTextBlock</a></span> currentBlock <span class="operator">=</span> textDocument<span class="operator">-</span><span class="operator">&gt;</span>begin();

      <span class="keyword">while</span> (currentBlock<span class="operator">.</span>isValid()) {
          processBlock(currentBlock);
          currentBlock <span class="operator">=</span> currentBlock<span class="operator">.</span>next();
      }

</pre>
<p>This method is useful for when you want to extract just the rich text from a document because it ignores frames, tables, and other types of structure.</p>
<p><a href="qtextblock.html">QTextBlock</a> provides comparison operators that make it easier to manipulate blocks: <a href="qtextblock.html#operator-eq-eq">operator==</a>() and <a href="qtextblock.html#operator-not-eq">operator!=</a>() are used to test whether two blocks are the same, and <a href="qtextblock.html#operator-lt">operator&lt;</a>() is used to determine which one occurs first in a document.</p>
<a name="frames"></a>
<h3 id="frames">Frames</h3>
<p>Frames are provided by the <a href="qtextframe.html">QTextFrame</a> class.</p>
<p>Text frames group together blocks of text and child frames, creating document structures that are larger than paragraphs. The format of a frame specifies how it is rendered and positioned on the page. Frames are either inserted into the text flow, or they float on the left or right hand side of the page. Each document contains a root frame that contains all the other document elements. As a result, all frames except the root frame have a parent frame.</p>
<p>Since text blocks are used to separate other document elements, each frame will always contain at least one text block, and zero or more child frames. We can inspect the contents of a frame by using a <a href="qtextframe-iterator.html">QTextFrame::iterator</a> to traverse the frame's child elements:</p>
<pre class="cpp">

      <span class="type">QDomElement</span> frameElement <span class="operator">=</span> <span class="operator">.</span><span class="operator">.</span><span class="operator">.</span>

      <span class="type"><a href="qtextframe.html">QTextFrame</a></span><span class="operator">::</span>iterator it;
      <span class="keyword">for</span> (it <span class="operator">=</span> frame<span class="operator">-</span><span class="operator">&gt;</span>begin(); <span class="operator">!</span>(it<span class="operator">.</span>atEnd()); <span class="operator">+</span><span class="operator">+</span>it) {

          <span class="type"><a href="qtextframe.html">QTextFrame</a></span> <span class="operator">*</span>childFrame <span class="operator">=</span> it<span class="operator">.</span>currentFrame();
          <span class="type"><a href="qtextblock.html">QTextBlock</a></span> childBlock <span class="operator">=</span> it<span class="operator">.</span>currentBlock();

          <span class="keyword">if</span> (childFrame)
              processFrame(frameElement<span class="operator">,</span> childFrame);
          <span class="keyword">else</span> <span class="keyword">if</span> (childBlock<span class="operator">.</span>isValid())
              processBlock(frameElement<span class="operator">,</span> childBlock);
      }

</pre>
<p>Note that the iterator selects both frames and blocks, so it is necessary to check which it is referring to. This allows us to navigate the document structure on a frame-by-frame basis yet still access text blocks if required. Both the <a href="qtextblock-iterator.html">QTextBlock::iterator</a> and <a href="qtextframe-iterator.html">QTextFrame::iterator</a> classes can be used in complementary ways to extract the required structure from a document.</p>
<a name="tables"></a>
<h3 id="tables">Tables</h3>
<p>Tables are provided by the <a href="qtexttable.html">QTextTable</a> class.</p>
<p>Tables are collections of cells that are arranged in rows and columns. Each table cell is a document element with its own character format, but it can also contain other elements, such as frames and text blocks. Table cells are automatically created when the table is constructed, or when extra rows or columns are added. They can also be moved between tables.</p>
<p><a href="qtexttable.html">QTextTable</a> is a subclass of <a href="qtextframe.html">QTextFrame</a>, so tables are treated like frames in the document structure. For each frame that we encounter in the document, we can test whether it represents a table, and deal with it in a different way:</p>
<pre class="cpp">

      <span class="type">QDomElement</span> frameElement <span class="operator">=</span> <span class="operator">.</span><span class="operator">.</span><span class="operator">.</span>

      <span class="type"><a href="qtextframe.html">QTextFrame</a></span><span class="operator">::</span>iterator it;
      <span class="keyword">for</span> (it <span class="operator">=</span> frame<span class="operator">-</span><span class="operator">&gt;</span>begin(); <span class="operator">!</span>(it<span class="operator">.</span>atEnd()); <span class="operator">+</span><span class="operator">+</span>it) {

          <span class="type"><a href="qtextframe.html">QTextFrame</a></span> <span class="operator">*</span>childFrame <span class="operator">=</span> it<span class="operator">.</span>currentFrame();
          <span class="type"><a href="qtextblock.html">QTextBlock</a></span> childBlock <span class="operator">=</span> it<span class="operator">.</span>currentBlock();

          <span class="keyword">if</span> (childFrame) {
              <span class="type"><a href="qtexttable.html">QTextTable</a></span> <span class="operator">*</span>childTable <span class="operator">=</span> qobject_cast<span class="operator">&lt;</span><span class="type"><a href="qtexttable.html">QTextTable</a></span><span class="operator">*</span><span class="operator">&gt;</span>(childFrame);

              <span class="keyword">if</span> (childTable)
                  processTable(frameElement<span class="operator">,</span> childTable);
              <span class="keyword">else</span>
                  processFrame(frameElement<span class="operator">,</span> childFrame);

          } <span class="keyword">else</span> <span class="keyword">if</span> (childBlock<span class="operator">.</span>isValid())
              processBlock(frameElement<span class="operator">,</span> childBlock);
      }

</pre>
<p>The cells within an existing table can be examined by iterating through the rows and columns.</p>
<pre class="cpp">

      <span class="keyword">for</span> (<span class="type">int</span> row <span class="operator">=</span> <span class="number">0</span>; row <span class="operator">&lt;</span> table<span class="operator">-</span><span class="operator">&gt;</span>rows(); <span class="operator">+</span><span class="operator">+</span>row) {
          <span class="keyword">for</span> (<span class="type">int</span> column <span class="operator">=</span> <span class="number">0</span>; column <span class="operator">&lt;</span> table<span class="operator">-</span><span class="operator">&gt;</span>columns(); <span class="operator">+</span><span class="operator">+</span>column) {
              <span class="type"><a href="qtexttablecell.html">QTextTableCell</a></span> tableCell <span class="operator">=</span> table<span class="operator">-</span><span class="operator">&gt;</span>cellAt(row<span class="operator">,</span> column);
              processTableCell(tableCell);
          }
      }

</pre>
<a name="lists"></a>
<h3 id="lists">Lists</h3>
<p>Lists are provided by the <a href="qtextlist.html">QTextList</a> class.</p>
<p>Lists are sequences of text blocks that are formatted in the usual way, but which also provide the standard list decorations such as bullet points and enumerated items. Lists can be nested, and will be indented if the list's format specifies a non-zero indentation.</p>
<p>We can refer to each list item by its index in the list:</p>
<pre class="cpp">

      <span class="keyword">for</span> (<span class="type">int</span> index <span class="operator">=</span> <span class="number">0</span>; index <span class="operator">&lt;</span> list<span class="operator">-</span><span class="operator">&gt;</span>count(); <span class="operator">+</span><span class="operator">+</span>index) {
          <span class="type"><a href="qtextblock.html">QTextBlock</a></span> listItem <span class="operator">=</span> list<span class="operator">-</span><span class="operator">&gt;</span>item(index);
          processListItem(listItem);
      }

</pre>
<p>Since <a href="qtextlist.html">QTextList</a> is a subclass of <a href="qtextblockgroup.html">QTextBlockGroup</a>, it does not group the list items as child elements, but instead provides various functions for managing them. This means that any text block we find when traversing a document may actually be a list item. We can ensure that list items are correctly identified by using the following code:</p>
<pre class="cpp">

      <span class="type"><a href="qtextframe.html">QTextFrame</a></span><span class="operator">::</span>iterator it;
      <span class="keyword">for</span> (it <span class="operator">=</span> frame<span class="operator">-</span><span class="operator">&gt;</span>begin(); <span class="operator">!</span>(it<span class="operator">.</span>atEnd()); <span class="operator">+</span><span class="operator">+</span>it) {

          <span class="type"><a href="qtextblock.html">QTextBlock</a></span> block <span class="operator">=</span> it<span class="operator">.</span>currentBlock();

          <span class="keyword">if</span> (block<span class="operator">.</span>isValid()) {

              <span class="type"><a href="qtextlist.html">QTextList</a></span> <span class="operator">*</span>list <span class="operator">=</span> block<span class="operator">.</span>textList();

              <span class="keyword">if</span> (list) {
                  <span class="type">int</span> index <span class="operator">=</span> list<span class="operator">-</span><span class="operator">&gt;</span>itemNumber(block);
                  processListItem(list, index);
              }
          }
      }

</pre>
<a name="images"></a>
<h3 id="images">Images</h3>
<p>Images in <a href="qtextdocument.html">QTextDocument</a> are represented by text fragments that reference external images via the resource mechanism. Images are created using the cursor interface, and can be modified later by changing the character format of the image's text fragment:</p>
<pre class="cpp">

      <span class="keyword">if</span> (fragment<span class="operator">.</span>isValid()) {
          <span class="type"><a href="qtextimageformat.html">QTextImageFormat</a></span> newImageFormat <span class="operator">=</span> fragment<span class="operator">.</span>charFormat()<span class="operator">.</span>toImageFormat();

          <span class="keyword">if</span> (newImageFormat<span class="operator">.</span>isValid()) {
              newImageFormat<span class="operator">.</span>setName(<span class="string">&quot;:/images/newimage.png&quot;</span>);
              <span class="type"><a href="qtextcursor.html">QTextCursor</a></span> helper <span class="operator">=</span> cursor;

              helper<span class="operator">.</span>setPosition(fragment<span class="operator">.</span>position());
              helper<span class="operator">.</span>setPosition(fragment<span class="operator">.</span>position() <span class="operator">+</span> fragment<span class="operator">.</span>length()<span class="operator">,</span>
                                  <span class="type"><a href="qtextcursor.html">QTextCursor</a></span><span class="operator">::</span>KeepAnchor);
              helper<span class="operator">.</span>setCharFormat(newImageFormat);
          }
      }

</pre>
<p>The fragment that represents the image can be found by iterating over the fragments in the text block that contains the image.</p>
</div>
<!-- @@@richtext-structure.html -->
<p class="naviNextPrevious footerNavi">
<a class="prevPage" href="richtext.html">Rich Text Processing</a>
<span class="naviSeparator">  &#9702;  </span>
<a class="nextPage" href="richtext-cursor.html">The QTextCursor Interface</a>
</p>
        </div>
       </div>
   </div>
   </div>
</div>
<div class="footer">
   <p>
   <acronym title="Copyright">&copy;</acronym> 2020 The Qt Company Ltd.
   Documentation contributions included herein are the copyrights of
   their respective owners.<br/>    The documentation provided herein is licensed under the terms of the    <a href="http://www.gnu.org/licenses/fdl.html">GNU Free Documentation    License version 1.3</a> as published by the Free Software Foundation.<br/>    Qt and respective logos are trademarks of The Qt Company Ltd.     in Finland and/or other countries worldwide. All other trademarks are property
   of their respective owners. </p>
</div>
</body>
</html>
